Outline

  1. Make a data folder

  2. Drag favorability.csv into the data folder

  3. Make existing folder and RStudio project

  4. Open an R Markdown Notebook

  5. library(tidyverses) plus other libraries

  6. IMPORT data See Also RStudio data import wizard

  7. ATTACHE data

  8. EDA: Visualize ggplot(data = starwars, aes(hair_color)) + geom_bar()

  9. EDA: skimr::skim(starwars)

  10. EDA: summary(fav_rating)

  11. left_join(starwars, fivethirtyeight)

  12. Transform data: five dplyr verbs …

    • count / group_by & summarize
  13. Interactive visualization ggplotly

  14. Quick Linear Regression

  15. Reports: notebooks, slides, dashboards, word document, PDF, book, etc.


5. library(tidyverses) plus other libraries

library(tidyverse)
library(skimr)
library(plotly)
library(moderndive)
library(broom)

6. read_csv(file_name.csv)

See Also data import wizard

## fav_data <- read_csv("data/fav.csv")
favorability <- read_csv("https://raw.githubusercontent.com/libjohn/intro2r-code/master/data/538_favorability_popularity.csv", skip = 11)

7 attached on-board data

dplyr::starwars

data("starwars")

8 Quick visualization

Visualize with the ggplot2 library.

plot <- ggplot(data = starwars, 
               aes(x = hair_color)) + 
  geom_bar()
plot

One improvement

Arrange bars by frequency using forcats::fct_infreq()

plot1 <- ggplot(starwars, 
                aes(fct_infreq(hair_color))) + 
  geom_bar()
plot1

9. skimr::skim(starwars)

The skimr library presents summary EDA results using the skim() function

skim(starwars)
-- Data Summary ------------------------
                           Values  
Name                       starwars
Number of rows             87      
Number of columns          14      
_______________________            
Column type frequency:             
  character                8       
  list                     3       
  numeric                  3       
________________________           
Group variables            None    

-- Variable type: character --------------------------------------------------------------------------------
# A tibble: 8 x 8
  skim_variable n_missing complete_rate   min   max empty n_unique whitespace
* <chr>             <int>         <dbl> <int> <int> <int>    <int>      <int>
1 name                  0         1         3    21     0       87          0
2 hair_color            5         0.943     4    13     0       12          0
3 skin_color            0         1         3    19     0       31          0
4 eye_color             0         1         3    13     0       15          0
5 sex                   4         0.954     4    14     0        4          0
6 gender                4         0.954     8     9     0        2          0
7 homeworld            10         0.885     4    14     0       48          0
8 species               4         0.954     3    14     0       37          0

-- Variable type: list -------------------------------------------------------------------------------------
# A tibble: 3 x 6
  skim_variable n_missing complete_rate n_unique min_length max_length
* <chr>             <int>         <dbl>    <int>      <int>      <int>
1 films                 0             1       24          1          7
2 vehicles              0             1       11          0          2
3 starships             0             1       17          0          5

-- Variable type: numeric ----------------------------------------------------------------------------------
# A tibble: 3 x 11
  skim_variable n_missing complete_rate  mean    sd    p0   p25   p50   p75  p100 hist 
* <chr>             <int>         <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <chr>
1 height                6         0.931 174.   34.8    66 167     180 191     264 ▁▁▇▅▁
2 mass                 28         0.678  97.3 169.     15  55.6    79  84.5  1358 ▇▁▁▁▁
3 birth_year           44         0.494  87.6 155.      8  35      52  72     896 ▇▁▁▁▁

10. summary

summary(favorability)
     name             fav_rating   
 Length:14          Min.   :110.0  
 Class :character   1st Qu.:148.5  
 Mode  :character   Median :392.0  
                    Mean   :369.0  
                    3rd Qu.:559.5  
                    Max.   :610.0  

11. left_join(starwars, fivethirtyeight)

Joins or merges are part of thedplyr library.

starwars %>% 
  left_join(favorability, by = "name") %>% 
  select(name, fav_rating, everything()) %>% 
  arrange(-fav_rating)

12. Transform data:

From the dplyr library, use the five verbs …

select to subset data by columns

starwars %>% 
  select(name, gender, hair_color)

filter to subset data rows

starwars %>% 
  filter(gender == "feminine")

arrange to sort data

starwars %>% 
  arrange(desc(height), desc(name))

mutate to add new variable or transform existing

starwars %>%
  drop_na(mass) %>% 
  select(name, mass) %>% 
  mutate(big_mass = mass * 2)

count / group_by & summarize

subtotals of variables

starwars %>% 
  count(gender)

Variable totals (and also, but not here, calculations)

starwars %>% 
  drop_na(mass) %>% 
  summarise(sum(mass))

Variable subtotals and calculations

group_by(gender, species) %>% summarise(mean_height = mean(height), total = n())

starwars %>% 
  drop_na(height) %>% 
  group_by(gender, species) %>% 
  summarise(mean_height = mean(height), total = n()) %>% 
  arrange(desc(total)) %>%
  drop_na(species) %>%
  filter(total > 1) %>% 
  select(species, gender, total, everything())

13. Interactive visualization

from the plotly library

ggplotly(plot1)

14. Regression / models

Predict mass from height after eliminating Jabba from the data set. Here we’ll use primarily base R, moderndive for model outputs, and tidyverse for the pipe %>% and dplyr for data transformations. Plus, alternatively, the broom library to manipulate models.

model <- lm(mass ~ height, data = starwars %>% filter(mass < 500))
model

Call:
lm(formula = mass ~ height, data = starwars %>% filter(mass < 
    500))

Coefficients:
(Intercept)       height  
   -32.5408       0.6214  
summary(model)

Call:
lm(formula = mass ~ height, data = starwars %>% filter(mass < 
    500))

Residuals:
    Min      1Q  Median      3Q     Max 
-39.382  -8.212   0.211   3.846  57.327 

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept) -32.54076   12.56053  -2.591   0.0122 *  
height        0.62136    0.07073   8.785 4.02e-12 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 19.14 on 56 degrees of freedom
Multiple R-squared:  0.5795,    Adjusted R-squared:  0.572 
F-statistic: 77.18 on 1 and 56 DF,  p-value: 4.018e-12

A nice Explanation of Basic Regression can be found in chapter 5 of the book Statistical Inference via Data Science. You can also use the moderndive library packages to access helpful functions such as: get_correlatin(), get_regression_table(), etc.

You may also appreciate or prefer the broom package for the very nice tidy(), glance(), and augment() functions.

starwars %>% 
  filter(mass < 500) %>% 
  get_correlation(mass ~ height)
# tidy(model)
get_regression_table(model)
# broom::glance(model)
get_regression_summaries(model)
# broom::augment(model)
get_regression_points(model)

Visualize regression

mass over height with a fitted linear regression line and confidence interval using geom_smooth()

starwars %>% 
  filter(mass < 500) %>%
  ggplot(aes(height, mass)) +
  geom_jitter() +
  geom_smooth(method = "lm")

15. Render reports

By changing the argument in the YAML header, you can render many report styles. A few popular examples include

type YAML syntax More information
notebook (alpha or dev) output: html_notebook Notebook
notebook (final or prod) output: html_document HTML document
Word document output: word_document MS Word
slide deck See Get Started Xaringan
dashboards   flexdashboard or shiny
e-book / web-book   Bookdown
website   Blogdown
website (simple) Create a website / Distill
PDF output: pdf_document PDF document
LS0tDQp0aXRsZTogIlF1aWNrc3RhcnQgZGVtbyINCmF1dGhvcjogIkpvaG4gTGl0dGxlIg0KZGF0ZTogImByIFN5cy5EYXRlKClgIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KIyMgT3V0bGluZQ0KDQoxLiBNYWtlIGEgZGF0YSBmb2xkZXINCjEuIERyYWcgZmF2b3JhYmlsaXR5LmNzdiBpbnRvIHRoZSBkYXRhIGZvbGRlcg0KMS4gTWFrZSBleGlzdGluZyBmb2xkZXIgYW5kIFJTdHVkaW8gcHJvamVjdA0KMS4gT3BlbiBhbiBSIE1hcmtkb3duIE5vdGVib29rDQoxLiBgbGlicmFyeSh0aWR5dmVyc2VzKWAgIHBsdXMgb3RoZXIgbGlicmFyaWVzDQoxLiBJTVBPUlQgZGF0YSBTZWUgQWxzbyBfUlN0dWRpbyBkYXRhIGltcG9ydCB3aXphcmRfDQoxLiBBVFRBQ0hFIGRhdGENCjEuIEVEQTogVmlzdWFsaXplIGBnZ3Bsb3QoZGF0YSA9IHN0YXJ3YXJzLCBhZXMoaGFpcl9jb2xvcikpICsgZ2VvbV9iYXIoKWAgDQoxLiBFREE6IGBza2ltcjo6c2tpbShzdGFyd2FycylgDQoxLiBFREE6IHN1bW1hcnkoZmF2X3JhdGluZykNCjEuIGBsZWZ0X2pvaW4oc3RhcndhcnMsIGZpdmV0aGlydHllaWdodClgDQoxLiBUcmFuc2Zvcm0gZGF0YTogZml2ZSBkcGx5ciB2ZXJicyAuLi4NCg0KICAgIC0gYGNvdW50YCAvIGBncm91cF9ieWAgJiBgc3VtbWFyaXplYA0KICAgICAgICANCjEuIEludGVyYWN0aXZlIHZpc3VhbGl6YXRpb24gZ2dwbG90bHkNCjEuIFF1aWNrIExpbmVhciBSZWdyZXNzaW9uDQoxLiBSZXBvcnRzOiAgbm90ZWJvb2tzLCBzbGlkZXMsIGRhc2hib2FyZHMsIHdvcmQgZG9jdW1lbnQsIFBERiwgYm9vaywgZXRjLg0KDQotLS0NCg0KIyMgNS4gYGxpYnJhcnkodGlkeXZlcnNlcylgICBwbHVzIG90aGVyIGxpYnJhcmllcw0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KHNraW1yKQ0KbGlicmFyeShwbG90bHkpDQpsaWJyYXJ5KG1vZGVybmRpdmUpDQpsaWJyYXJ5KGJyb29tKQ0KYGBgDQoNCiMjIDYuIGByZWFkX2NzdihmaWxlX25hbWUuY3N2KWAgICANCg0KU2VlIEFsc28gW2RhdGEgaW1wb3J0IHdpemFyZF0oaHR0cHM6Ly9zdXBwb3J0LnJzdHVkaW8uY29tL2hjL2VuLXVzL2FydGljbGVzLzIxODYxMTk3Ny1JbXBvcnRpbmctRGF0YS13aXRoLVJTdHVkaW8pDQoNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQojIyBmYXZfZGF0YSA8LSByZWFkX2NzdigiZGF0YS9mYXYuY3N2IikNCmZhdm9yYWJpbGl0eSA8LSByZWFkX2NzdigiaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2xpYmpvaG4vaW50cm8yci1jb2RlL21hc3Rlci9kYXRhLzUzOF9mYXZvcmFiaWxpdHlfcG9wdWxhcml0eS5jc3YiLCBza2lwID0gMTEpDQpgYGANCg0KDQojIyA3IGF0dGFjaGVkIG9uLWJvYXJkIGRhdGENCg0KLSBkcGx5cjo6c3RhcndhcnMNCg0KYGRwbHlyOjpzdGFyd2Fyc2ANCg0KYGBge3J9DQpkYXRhKCJzdGFyd2FycyIpDQpgYGANCg0KIyMgOCBRdWljayB2aXN1YWxpemF0aW9uDQoNClZpc3VhbGl6ZSB3aXRoIHRoZSBgZ2dwbG90MmAgbGlicmFyeS4NCg0KYGBge3J9DQpwbG90IDwtIGdncGxvdChkYXRhID0gc3RhcndhcnMsIA0KICAgICAgICAgICAgICAgYWVzKHggPSBoYWlyX2NvbG9yKSkgKyANCiAgZ2VvbV9iYXIoKQ0KcGxvdA0KYGBgDQoNCiMjIyBPbmUgaW1wcm92ZW1lbnQNCg0KQXJyYW5nZSBiYXJzIGJ5IGZyZXF1ZW5jeSB1c2luZyBgZm9yY2F0czo6ZmN0X2luZnJlcSgpYA0KDQoNCmBgYHtyfQ0KcGxvdDEgPC0gZ2dwbG90KHN0YXJ3YXJzLCANCiAgICAgICAgICAgICAgICBhZXMoZmN0X2luZnJlcShoYWlyX2NvbG9yKSkpICsgDQogIGdlb21fYmFyKCkNCnBsb3QxDQpgYGANCg0KDQojIyA5LiBgc2tpbXI6OnNraW0oc3RhcndhcnMpYA0KDQpUaGUgYHNraW1yYCBsaWJyYXJ5IHByZXNlbnRzIHN1bW1hcnkgRURBIHJlc3VsdHMgdXNpbmcgdGhlIGBza2ltKClgIGZ1bmN0aW9uIA0KDQpgYGB7cn0NCnNraW0oc3RhcndhcnMpDQpgYGANCg0KIyMgMTAuIHN1bW1hcnkNCg0KYGBge3J9DQpzdW1tYXJ5KGZhdm9yYWJpbGl0eSkNCmBgYA0KDQojIyAxMS4gYGxlZnRfam9pbihzdGFyd2FycywgZml2ZXRoaXJ0eWVpZ2h0KWANCg0KW0pvaW5zXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvYXJ0aWNsZXMvdHdvLXRhYmxlLmh0bWwpIG9yIG1lcmdlcyBhcmUgcGFydCBvZiB0aGVgZHBseXJgIGxpYnJhcnkuDQoNCmBgYHtyfQ0Kc3RhcndhcnMgJT4lIA0KICBsZWZ0X2pvaW4oZmF2b3JhYmlsaXR5LCBieSA9ICJuYW1lIikgJT4lIA0KICBzZWxlY3QobmFtZSwgZmF2X3JhdGluZywgZXZlcnl0aGluZygpKSAlPiUgDQogIGFycmFuZ2UoLWZhdl9yYXRpbmcpDQpgYGANCg0KDQojIyAxMi4gVHJhbnNmb3JtIGRhdGE6IA0KDQpGcm9tIHRoZSBgZHBseXJgIGxpYnJhcnksIHVzZSB0aGUgZml2ZSAgdmVyYnMgLi4uDQoNCiMjIyBgc2VsZWN0YCB0byBzdWJzZXQgZGF0YSBieSBjb2x1bW5zDQoNCmBgYHtyfQ0Kc3RhcndhcnMgJT4lIA0KICBzZWxlY3QobmFtZSwgZ2VuZGVyLCBoYWlyX2NvbG9yKQ0KYGBgDQoNCiMjIyBgZmlsdGVyYCB0byBzdWJzZXQgZGF0YSByb3dzIA0KDQpgYGB7cn0NCnN0YXJ3YXJzICU+JSANCiAgZmlsdGVyKGdlbmRlciA9PSAiZmVtaW5pbmUiKQ0KYGBgDQoNCiMjIyBgYXJyYW5nZWAgdG8gc29ydCBkYXRhDQoNCmBgYHtyfQ0Kc3RhcndhcnMgJT4lIA0KICBhcnJhbmdlKGRlc2MoaGVpZ2h0KSwgZGVzYyhuYW1lKSkNCmBgYA0KDQojIyMgYG11dGF0ZWAgdG8gYWRkIG5ldyB2YXJpYWJsZSBvciB0cmFuc2Zvcm0gZXhpc3RpbmcNCg0KYGBge3J9DQpzdGFyd2FycyAlPiUNCiAgZHJvcF9uYShtYXNzKSAlPiUgDQogIHNlbGVjdChuYW1lLCBtYXNzKSAlPiUgDQogIG11dGF0ZShiaWdfbWFzcyA9IG1hc3MgKiAyKQ0KYGBgDQoNCg0KIyMjIGBjb3VudGAgLyBgZ3JvdXBfYnlgICYgYHN1bW1hcml6ZWANCg0Kc3VidG90YWxzIG9mIHZhcmlhYmxlcw0KDQoNCmBgYHtyfQ0Kc3RhcndhcnMgJT4lIA0KICBjb3VudChnZW5kZXIpDQpgYGANCg0KVmFyaWFibGUgdG90YWxzIChhbmQgYWxzbywgYnV0IG5vdCBoZXJlLCBjYWxjdWxhdGlvbnMpDQoNCmBgYHtyfQ0Kc3RhcndhcnMgJT4lIA0KICBkcm9wX25hKG1hc3MpICU+JSANCiAgc3VtbWFyaXNlKHN1bShtYXNzKSkNCmBgYA0KDQpWYXJpYWJsZSBzdWJ0b3RhbHMgYW5kIGNhbGN1bGF0aW9ucw0KDQo+IGBncm91cF9ieShnZW5kZXIsIHNwZWNpZXMpICU+JSANCiAgIHN1bW1hcmlzZShtZWFuX2hlaWdodCA9IG1lYW4oaGVpZ2h0KSwgdG90YWwgPSBuKCkpYA0KDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Kc3RhcndhcnMgJT4lIA0KICBkcm9wX25hKGhlaWdodCkgJT4lIA0KICBncm91cF9ieShnZW5kZXIsIHNwZWNpZXMpICU+JSANCiAgc3VtbWFyaXNlKG1lYW5faGVpZ2h0ID0gbWVhbihoZWlnaHQpLCB0b3RhbCA9IG4oKSkgJT4lIA0KICBhcnJhbmdlKGRlc2ModG90YWwpKSAlPiUNCiAgZHJvcF9uYShzcGVjaWVzKSAlPiUNCiAgZmlsdGVyKHRvdGFsID4gMSkgJT4lIA0KICBzZWxlY3Qoc3BlY2llcywgZ2VuZGVyLCB0b3RhbCwgZXZlcnl0aGluZygpKQ0KYGBgDQoNCiMjIDEzLiBJbnRlcmFjdGl2ZSB2aXN1YWxpemF0aW9uDQoNCmZyb20gdGhlIGBwbG90bHlgIGxpYnJhcnkNCg0KDQpgYGB7cn0NCmdncGxvdGx5KHBsb3QxKQ0KYGBgDQoNCiMjIDE0LiBSZWdyZXNzaW9uIC8gbW9kZWxzDQoNClByZWRpY3QgbWFzcyBmcm9tIGhlaWdodCBhZnRlciBlbGltaW5hdGluZyBKYWJiYSBmcm9tIHRoZSBkYXRhIHNldC4gIEhlcmUgd2UnbGwgdXNlIHByaW1hcmlseSBiYXNlIFIsIGBtb2Rlcm5kaXZlYCBmb3IgbW9kZWwgb3V0cHV0cywgYW5kIHRpZHl2ZXJzZSBmb3IgdGhlIHBpcGUgYCU+JWAgYW5kIGBkcGx5cmAgZm9yIGRhdGEgdHJhbnNmb3JtYXRpb25zLiAgUGx1cywgYWx0ZXJuYXRpdmVseSwgdGhlIGBicm9vbWAgbGlicmFyeSB0byBtYW5pcHVsYXRlIG1vZGVscy4gDQoNCmBgYHtyfQ0KbW9kZWwgPC0gbG0obWFzcyB+IGhlaWdodCwgZGF0YSA9IHN0YXJ3YXJzICU+JSBmaWx0ZXIobWFzcyA8IDUwMCkpDQptb2RlbA0Kc3VtbWFyeShtb2RlbCkNCmBgYA0KDQpBIG5pY2UgX0V4cGxhbmF0aW9uIG9mIEJhc2ljIFJlZ3Jlc3Npb25fIGNhbiBiZSBmb3VuZCBpbiBbY2hhcHRlciA1XShodHRwczovL21vZGVybmRpdmUuY29tLzUtcmVncmVzc2lvbi5odG1sKSBvZiB0aGUgYm9vayBbX1N0YXRpc3RpY2FsIEluZmVyZW5jZSB2aWEgRGF0YSBTY2llbmNlX10oaHR0cHM6Ly9tb2Rlcm5kaXZlLmNvbS8pLiAgWW91IGNhbiBhbHNvIHVzZSB0aGUgYG1vZGVybmRpdmVgDQpsaWJyYXJ5IHBhY2thZ2VzIHRvIGFjY2VzcyBoZWxwZnVsIGZ1bmN0aW9ucyBzdWNoIGFzOiAgYGdldF9jb3JyZWxhdGluKClgLCBgZ2V0X3JlZ3Jlc3Npb25fdGFibGUoKWAsIGV0Yy4NCg0KWW91IG1heSBhbHNvIGFwcHJlY2lhdGUgb3IgcHJlZmVyIHRoZSBbYnJvb21dKGh0dHBzOi8vYnJvb20udGlkeXZlcnNlLm9yZykgcGFja2FnZSBmb3IgdGhlIHZlcnkgbmljZSBgdGlkeSgpYCwgYGdsYW5jZSgpYCwgYW5kIGBhdWdtZW50KClgIGZ1bmN0aW9ucy4NCg0KYGBge3J9DQpzdGFyd2FycyAlPiUgDQogIGZpbHRlcihtYXNzIDwgNTAwKSAlPiUgDQogIGdldF9jb3JyZWxhdGlvbihtYXNzIH4gaGVpZ2h0KQ0KYGBgDQoNCg0KYGBge3J9DQojIHRpZHkobW9kZWwpDQpnZXRfcmVncmVzc2lvbl90YWJsZShtb2RlbCkNCmBgYA0KDQpgYGB7cn0NCiMgYnJvb206OmdsYW5jZShtb2RlbCkNCmdldF9yZWdyZXNzaW9uX3N1bW1hcmllcyhtb2RlbCkNCmBgYA0KDQoNCmBgYHtyfQ0KIyBicm9vbTo6YXVnbWVudChtb2RlbCkNCmdldF9yZWdyZXNzaW9uX3BvaW50cyhtb2RlbCkNCmBgYA0KDQojIyMgVmlzdWFsaXplIHJlZ3Jlc3Npb24NCg0KYG1hc3NgIG92ZXIgYGhlaWdodGAgd2l0aCBhIGZpdHRlZCBsaW5lYXIgcmVncmVzc2lvbiBsaW5lIGFuZCBjb25maWRlbmNlIGludGVydmFsIHVzaW5nIGBnZW9tX3Ntb290aCgpYA0KDQpgYGB7cn0NCnN0YXJ3YXJzICU+JSANCiAgZmlsdGVyKG1hc3MgPCA1MDApICU+JQ0KICBnZ3Bsb3QoYWVzKGhlaWdodCwgbWFzcykpICsNCiAgZ2VvbV9qaXR0ZXIoKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIpDQpgYGANCg0KIyMgMTUuIFJlbmRlciByZXBvcnRzDQoNCkJ5IGNoYW5naW5nIHRoZSBhcmd1bWVudCBpbiB0aGUgWUFNTCBoZWFkZXIsIHlvdSBjYW4gcmVuZGVyIG1hbnkgcmVwb3J0IHN0eWxlcy4gIEEgZmV3IHBvcHVsYXIgZXhhbXBsZXMgaW5jbHVkZQ0KDQp0eXBlIHwgWUFNTCBzeW50YXggfCBNb3JlIGluZm9ybWF0aW9uDQotLS0gfCAtLS0gfCAtLS0NCm5vdGVib29rIChhbHBoYSBvciBkZXYpIHwgb3V0cHV0OiBodG1sX25vdGVib29rIHwgW05vdGVib29rXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vbm90ZWJvb2suaHRtbCkNCm5vdGVib29rIChmaW5hbCBvciBwcm9kKSB8IG91dHB1dDogaHRtbF9kb2N1bWVudCB8IFtIVE1MIGRvY3VtZW50XShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vaHRtbC1kb2N1bWVudC5odG1sKQ0KV29yZCBkb2N1bWVudCB8IG91dHB1dDogd29yZF9kb2N1bWVudCB8IFtNUyBXb3JkXShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vd29yZC1kb2N1bWVudC5odG1sKQ0Kc2xpZGUgZGVjayB8IFNlZSBbR2V0IFN0YXJ0ZWRdKGh0dHBzOi8vc2xpZGVzLnlpaHVpLm9yZy94YXJpbmdhbi8jNCkgfCBbWGFyaW5nYW5dKGh0dHBzOi8vc2xpZGVzLnlpaHVpLm9yZy94YXJpbmdhbi8jMSkNCmRhc2hib2FyZHMgfCAmbmJzcDsgfCBbZmxleGRhc2hib2FyZF0oaHR0cHM6Ly9ybWFya2Rvd24ucnN0dWRpby5jb20vZmxleGRhc2hib2FyZC8pIG9yIFtzaGlueV0oaHR0cHM6Ly9zaGlueS5yc3R1ZGlvLmNvbS8pDQplLWJvb2sgLyB3ZWItYm9vayB8ICZuYnNwOyB8IFtCb29rZG93bl0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvYm9va2Rvd24vKQ0Kd2Vic2l0ZSB8ICZuYnNwOyB8IFtCbG9nZG93bl0oaHR0cHM6Ly9ib29rZG93bi5vcmcveWlodWkvYmxvZ2Rvd24vKQ0Kd2Vic2l0ZSAoc2ltcGxlKSB8IHwgW0NyZWF0ZSBhIHdlYnNpdGUgLyBEaXN0aWxsXShodHRwczovL3JzdHVkaW8uZ2l0aHViLmlvL2Rpc3RpbGwvd2Vic2l0ZS5odG1sKQ0KUERGIHwgb3V0cHV0OiBwZGZfZG9jdW1lbnQgfCBbUERGIGRvY3VtZW50XShodHRwczovL2Jvb2tkb3duLm9yZy95aWh1aS9ybWFya2Rvd24vcGRmLWRvY3VtZW50Lmh0bWwpDQoNCg0KDQo=